/* -*- mode: c++ -*- */
/**
 * @file   Shapes.ih
 * @author Sebastien Fourey (GREYC)
 * @date   Feb. 2010
 *
 * @brief  Shapes inline methods
 * \@copyright
 * This source code is part of the Board project, a C++ library whose
 * purpose is to allow simple drawings in EPS, FIG or SVG files.
 * Copyright (C) 2007 Sebastien Fourey <http://foureys.users.greyc.fr/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace LibBoard {
Shape::Shape( Color penColor, Color fillColor,
              double lineWidth,
              LineStyle style,
              const LineCap cap,
              const LineJoin join,
              int depth )
   : _depth( depth ),
     _penColor( penColor ),
     _fillColor( fillColor ),
     _lineWidth( lineWidth ),
     _lineStyle( style ),
     _lineCap( cap ),
     _lineJoin( join )
{
}

Rect
Shape::bbox(LineWidthFlag flag) const
{
  return boundingBox(flag);
}

Shape &
Shape::operator++()
{
  ++_depth;
  return *this;
}

Shape &
Shape::operator--()
{
  --_depth;
  return *this;
}


int
Shape::depth() const
{
  return _depth;
}

const Color &
Shape::penColor() const
{
  return _penColor;
}

const Color &
Shape::fillColor() const
{
  return _fillColor;
}

Shape &
Shape::rotateDeg( double angle, const Point & center )
{
  return rotate( angle * ( M_PI / 180.0 ), center );
}

Shape &
Shape::rotateDeg( double angle )
{
  return rotate( angle * ( M_PI / 180.0 ), center() );
}

void
Shape::updateLineWidth(double s)
{
  if ( _lineWidthScaling ) {
     _lineWidth *= s;
  }
}


Dot::Dot( double x, double y,
          Color color,
          double lineWidth,
          int depth )
   : Shape( color,
            Color::Null,
            lineWidth, SolidStyle, RoundCap, MiterJoin, depth ),
     _x( x ), _y( y )
{
}

Line::Line( double x1, double y1, double x2, double y2,
            Color color,
            double lineWidth,
            const LineStyle style,
            const LineCap cap,
            const LineJoin join,
            int depth )
   : Shape( color, Color::Null, lineWidth, style, cap, join, depth ),
     _x1( x1 ), _y1( y1 ), _x2( x2 ), _y2( y2 )
{
}

Line::Line( Point a, Point b,
            Color color,
            double lineWidth,
            const LineStyle style,
            const LineCap cap,
            const LineJoin join,
            int depth )
   : Shape( color, Color::Null, lineWidth, style, cap, join, depth ),
     _x1( a.x ), _y1( a.y ), _x2( b.x ), _y2( b.y )
{
}

Arrow::Arrow( double x1, double y1, double x2, double y2,
              Color penColor, Color fillColor,
              double lineWidth,
              const LineStyle style,
              const LineCap cap,
              const LineJoin join,
              int depth )
   : Line( x1, y1, x2, y2, penColor, lineWidth, style, cap, join, depth )
{

   if ( fillColor == Color::Null ) {
      Shape::_fillColor = penColor;
   } else {
      Shape::_fillColor = fillColor;
   }
}


Arrow::Arrow( Point p1,
              Point p2,
              Color penColor, Color fillColor,
              double lineWidth,
              const LineStyle style,
              const LineCap cap,
              const LineJoin join,
              int depth )
   : Line( p1, p2, penColor, lineWidth, style, cap, join, depth )
{
   if ( fillColor == Color::Null ) {
      Shape::_fillColor = penColor;
   } else {
      Shape::_fillColor = fillColor;
   }
}


Polyline::Polyline( const std::vector<Point> & points, 
                    bool closed,
                    Color penColor, Color fillColor,
                    double lineWidth,
                    const LineStyle lineStyle,
                    const LineCap cap,
                    const LineJoin join,
                    int depth )
     : Shape( penColor, fillColor, lineWidth, lineStyle, cap, join, depth ),
     _path( points, closed )
{
}

Polyline::Polyline( const Path & path, 
                    Color penColor, Color fillColor,
                    double lineWidth,
                    const LineStyle lineStyle,
                    const LineCap cap,
                    const LineJoin join,
                    int depth )
   : Shape( penColor, fillColor, lineWidth, lineStyle, cap, join, depth ),
     _path( path )
{
}

Polyline::Polyline( bool closed, Color penColor, Color fillColor,
                    double lineWidth,
                    const LineStyle lineStyle,
                    const LineCap cap,
                    const LineJoin join,
                    int depth )
   : Shape( penColor, fillColor, lineWidth, lineStyle, cap, join, depth ),
     _path( closed )
{
}

std::size_t
Polyline::vertexCount() const
{
   return _path.size();
}

const Path &
Polyline::path() const
{
  return _path;
}

Rectangle::Rectangle( double left, double top, double width, double height,
                      Color penColor, Color fillColor,
                      double lineWidth,
                      const LineStyle style,
                      const LineCap cap,
                      const LineJoin join,
                      int depth )
   : Polyline( std::vector<Point>(), true, penColor, fillColor,
               lineWidth, style, cap, join, depth )
{
   _path << Point( left, top );
   _path << Point( left + width, top );
   _path << Point( left + width, top - height );
   _path << Point( left, top - height );
}

Rectangle::Rectangle( const Rect & rect,
                      Color penColor, Color fillColor,
                      double lineWidth,
                      const LineStyle style,
                      const LineCap cap,
                      const LineJoin join,
                      int depth )
   : Polyline( std::vector<Point>(), true, penColor, fillColor,
               lineWidth, style, cap, join, depth ) {
   _path << Point( rect.left, rect.top );
   _path << Point( rect.left + rect.width, rect.top );
   _path << Point( rect.left + rect.width, rect.top - rect.height );
   _path << Point( rect.left, rect.top - rect.height );
}


} // namespace LibBoard
